//特殊键值
#if (!defined(F1))
  #define F1	-1
  #define F2	-2
  #define F3	-3
  #define F4	-4
  #define F5	-5
  #define F6	-6
  #define F7	-7
  #define F8	-8
  #define F9	-9
  #define F10	-10
  #define F11	-11
  #define F12	-12
  #define ESC	-100  //Esc退出
  #define BCK	0x08  //Backspace回格
  #define TAB	0x09  //Tab制表
  #define LSH	-101  //Shift左上档
  #define LCT	-102  //Ctrl左控制
  #define LAL	-103  //Alt左换档
  #define FXU	-111  //方向上↑
  #define FXD	-112  //方向下↓
  #define FXL	-113  //方向左←
  #define FXR	-114  //方向右→
  #define XEN	-115  //Enter小键盘回车
  #define RCT	-116  //Ctrl右控制
  #define XXG	-117  // / 小键盘斜杠
  #define RSH	-118  //Shift右上档
  #define RAL	-119  //Alt右换档
  #define HME	-120  //Home起始
  #define PGU	-121  //PgUp上页
  #define END	-122  //END
  #define PGD	-123  //PgDn下页
  #define INS	-124  //Insert插入
  #define DEL	-125  //Delete删除
  #define WIN	-126  //Window左窗口
  #define RMN	-127  //Menu右菜单
#endif

/* asmhead.nas */
struct BOOTINFO { /* 0x0ff0-0x0fff */
	char cyls; /* 启动区读磁盘读到此为止 */
	char leds; /* 启动时键盘的LED的状态 */
	char vmode; /* 显卡模式为多少位彩色 */
	char reserve;
	short scrnx, scrny; /* 画面分辨率 */
	char *vram;
};
#define ADR_BOOTINFO	0x00000ff0
#define ADR_DISKIMG		0x00100000
#define CONSOLE_ROWS 30 //30行
#define CONSOLE_COLS 80 //80列, 一行可显示80个字

#define MAX_SHEETS		256
/*
flags枚举: 
0     窗口关闭(不显示)
0x01  桌面背景
0x02  桌面图标
0x10  应用窗口
0x20  带光标命令行窗口
0x99  鼠标
*/
struct SHEET {
	unsigned char *buf, *cmd, *title;
	int bxsize, bysize, vx0, vy0, col_inv, height, flags;
	struct SHTCTL *ctl;
	struct TASK *task;
};
struct SHTCTL {
	unsigned char *vram, *map;
	int xsize, ysize, top;
	struct SHEET *sheets[MAX_SHEETS];
	struct SHEET sheets0[MAX_SHEETS];
};
extern int tbshts[MAX_SHEETS]; //任务栏已打开应用
extern int tbshts_num; //任务栏已打开应用数量
typedef void (*FUNC)(struct SHEET *sht, int mx, int my, int id);

/* draw.c */
struct DLL_STRPICENV {	/* 64KB */
	int work[64 * 1024 / 4];
};
struct RGB {
	unsigned char b, g, r, t;
};
struct DRAW {
	char *name, *filebuf;
	struct RGB *picbuf;
	struct DLL_STRPICENV *env;
	int fsize, error, info[8];
	/* 
		error list
		1: File not found.
		2: File is not image.
	 */
};
int draw_info(struct DLL_STRPICENV *env, int *info, int size, char *fp);
int draw_decode0(int mode, struct DLL_STRPICENV *env, int size, char *fp, int b_type, char *buf, int jump);
unsigned char rgb2pal(int r, int g, int b, int x, int y);
struct DRAW *draw_init(char *name);
int draw_do(struct SHEET *sht, struct DRAW *pic, int px, int py);
void draw_free(struct DRAW *pic);

/* bmp.bak */
int info_BMP(struct DLL_STRPICENV *env, int *info, int size, char *fp);
int decode0_BMP(struct DLL_STRPICENV *env, int size, char *fp, int b_type, char *buf, int skip);

/* jpeg.c */
int info_JPG(struct DLL_STRPICENV *env, int *info, int size, char *fp);
int decode0_JPG(struct DLL_STRPICENV *env, int size, char *fp, int b_type, char *buf, int skip);

/* ico.c */
int info_ICO(struct DLL_STRPICENV *env, int *info, int size, char *fp);
int decode0_ICO(struct DLL_STRPICENV *env, int size, char *fp, int b_type, char *buf, int jump);

/* png.c */
int info_PNG(struct DLL_STRPICENV *env, int *info, int size, char *fp);
int decode0_PNG(struct DLL_STRPICENV *env, int size, char *fp, int b_type, char *buf, int jump);

/* naskfunc.nas */
extern char s_buf[128];
extern void putstr(char *str) __attribute__((cdecl));
void io_hlt(void);
void io_cli(void);
void io_sti(void);
void io_stihlt(void);
int io_in8(int port);
void io_out8(int port, int data);
int io_in16(int port);
void io_out16(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);
int io_inputkey(int mode);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);
int load_cr0(void);
void store_cr0(int cr0);
void load_tr(int tr);
void asm_inthandler0c(void);
void asm_inthandler0d(void);
void asm_inthandler20(void);
void asm_inthandler21(void);
void asm_inthandler2c(void);
unsigned int memtest_sub(unsigned int start, unsigned int end);
void farjmp(int eip, int cs);
void farcall(int eip, int cs);
void asm_hrb_api(void);
void start_app(int eip, int cs, int esp, int ds, int *tss_esp0);
void asm_end_app(void);
void shutdown2(void); 

/* fifo.c */
struct FIFO32 {
	int *buf;
	int p, q, size, free, flags;
	struct TASK *task;
};
void fifo32_init(struct FIFO32 *fifo, int size, int *buf, struct TASK *task);
int fifo32_put(struct FIFO32 *fifo, int data);
int fifo32_get(struct FIFO32 *fifo);
int fifo32_status(struct FIFO32 *fifo);

/* graphic.c */
int str2int(char *str);
void init_palette(void);
int get_pxdeep(void);
int get_color(int pxdeep, int col);
void picdata(unsigned int *vram, int xsize, int px, int py, unsigned char *data, int sx, int sy, int bc);
void set_palette(int start, int end, unsigned char *rgb);
void boxfill8(unsigned int *vram, int xsize, unsigned int c, int x0, int y0, int x1, int y1);
void init_screen8(struct SHEET *sht_back, int x, int y, char *fn, int bc);
void init_taskbar(unsigned int *vram, int xsize);
void show_taskbar();
struct SHEET *init_deskico(unsigned char *title, unsigned char *cmd, unsigned char *iconame);
void init_icos();
void icos_refresh();
void init_start(struct SHEET *sht);
void init_rightmenu(struct SHEET *sht);
void putfont8(unsigned int *vram, int xsize, int x, int y, int c, char *font);
void putfont16(unsigned int *vram, int xsize, int x, int y, int c, char *font);
void putfonts8_asc(unsigned int *vram, int xsize, int x, int y, int c, unsigned char *s);
void init_mouse_cursor8(unsigned int *mouse, int bc);
void putblock8_8(int *vram, int vxsize, int pxsize, int pysize, int px0, int py0, int *buf, int bxsize);
void rm_refresh_click(struct SHEET *sht, int mx, int my, int id);
void rm_console_click(struct SHEET *sht, int mx, int my, int id);
void rm_scrnpic_click(struct SHEET *sht, int mx, int my, int id);
void rm_scrnclr_click(struct SHEET *sht, int mx, int my, int id);
void rm_scrnclrs_click(struct SHEET *sht, int mx, int my, int id);
void rm_folder_click(struct SHEET* sht, int mx, int my, int id);
void sm_shutdown1_click(struct SHEET *sht, int mx, int my, int id);
void sm_opensub_click(struct SHEET *sht, int mx, int my, int id);
void sm_reboot_click(struct SHEET *sht, int mx, int my, int id);
void sm_start_click(struct SHEET *sht, int mx, int my, int id);
void sm_taskbar_click(struct SHEET *sht, int mx, int my, int id);
void sm_startsub_click(struct SHEET *sht, int mx, int my, int id);
#define COL8_000000		0x00000000
#define COL8_FF0000		0x00ff0000
#define COL8_00FF00		0x0000ff00
#define COL8_FFFF00		0x00ffff00
#define COL8_0000FF		0x000000ff
#define COL8_FF00FF		0x00ff00ff
#define COL8_00FFFF		0x0000ffff
#define COL8_FFFFFF		0x00ffffff
#define COL8_C6C6C6		0x00c6c6c6
#define COL8_840000		0x00840000
#define COL8_008400		0x00008400
#define COL8_848400		0x00848400
#define COL8_000084		0x00000084
#define COL8_840084		0x00840084
#define COL8_008484		0x00008484
#define COL8_848484		0x00848484

/* dsctbl.c */
struct SEGMENT_DESCRIPTOR {
	short limit_low, base_low;
	char base_mid, access_right;
	char limit_high, base_high;
};
struct GATE_DESCRIPTOR {
	short offset_low, selector;
	char dw_count, access_right;
	short offset_high;
};
void init_gdtidt(void);
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
#define ADR_IDT			0x0026f800
#define LIMIT_IDT		0x000007ff
#define ADR_GDT			0x00270000
#define LIMIT_GDT		0x0000ffff
#define ADR_BOTPAK		0x00280000
#define LIMIT_BOTPAK	0x0007ffff
#define AR_DATA32_RW	0x4092
#define AR_CODE32_ER	0x409a
#define AR_LDT			0x0082
#define AR_TSS32		0x0089
#define AR_INTGATE32	0x008e

/* int.c */
void init_pic(void);
#define PIC0_ICW1		0x0020
#define PIC0_OCW2		0x0020
#define PIC0_IMR		0x0021
#define PIC0_ICW2		0x0021
#define PIC0_ICW3		0x0021
#define PIC0_ICW4		0x0021
#define PIC1_ICW1		0x00a0
#define PIC1_OCW2		0x00a0
#define PIC1_IMR		0x00a1
#define PIC1_ICW2		0x00a1
#define PIC1_ICW3		0x00a1
#define PIC1_ICW4		0x00a1

/* keyboard.c */
void inthandler21(int *esp);
void wait_KBC_sendready(void);
void init_keyboard(struct FIFO32 *fifo, int data0);
#define PORT_KEYDAT		0x0060
#define PORT_KEYCMD		0x0064

/* mouse.c */
struct MOUSE_DEC {
	unsigned char buf[3], phase;
	int x, y, btn;
};
extern int MOUSEX, MOUSEY, MOUSEBTN;
void inthandler2c(int *esp);
void enable_mouse(struct FIFO32 *fifo, int data0, struct MOUSE_DEC *mdec);
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);

/* memory.c */
#define MEMMAN_FREES		4090	/* 约32KB */
#define MEMMAN_ADDR			0x003c0000
struct FREEINFO {	/* 剩余容量信息 */
	unsigned int addr, size;
};
struct MEMMAN {		/* 内存管理 */
	int frees, maxfrees, lostsize, losts;
	struct FREEINFO free[MEMMAN_FREES];
};
unsigned int memtest(unsigned int start, unsigned int end);
void memman_init(struct MEMMAN *man);
unsigned int memman_total(struct MEMMAN *man);
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);

/* sheet.c */
struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize);
struct SHEET *sheet_alloc(struct SHTCTL *ctl);
void sheet_setbuf(struct SHEET *sht, unsigned char *buf, int xsize, int ysize, int col_inv);
void sheet_updown(struct SHEET *sht, int height);
void sheet_refresh(struct SHEET *sht, int bx0, int by0, int bx1, int by1);
void sheet_slide(struct SHEET *sht, int vx0, int vy0);
void sheet_free(struct SHEET *sht);
int  sheet_getsize(int flags);

/* timer.c */
#define MAX_TIMER		500
struct TIMER {
	struct TIMER *next;
	unsigned int timeout;
	char flags, flags2;
	struct FIFO32 *fifo;
	int data;
};
struct TIMERCTL {
	unsigned int count, next;
	struct TIMER *t0;
	struct TIMER timers0[MAX_TIMER];
};
extern struct TIMERCTL timerctl;
void init_pit(void);
struct TIMER *timer_alloc(void);
void timer_free(struct TIMER *timer);
void timer_init(struct TIMER *timer, struct FIFO32 *fifo, int data);
void timer_settime(struct TIMER *timer, unsigned int timeout);
void inthandler20(int *esp);
int timer_cancel(struct TIMER *timer);
void timer_cancelall(struct FIFO32 *fifo);

/* mtask.c */
#define MAX_TASKS		1000	/*最大任务数量*/
#define TASK_GDT0		3		/*定义从GDT的几号开始分配给TSS */
#define MAX_TASKS_LV	100
#define MAX_TASKLEVELS	10
struct TSS32 {
	int backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;
	int eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
	int es, cs, ss, ds, fs, gs;
	int ldtr, iomap;
};
struct TASK {
	int sel, flags;		/* sel用来存放GDT的编号*/
	int level, priority; /* 优先级 */
	struct FIFO32 fifo;
	struct TSS32 tss;
	struct SEGMENT_DESCRIPTOR ldt[2];
	struct CONSOLE *cons;
	int ds_base, cons_stack;
	struct FILEHANDLE *fhandle;
	int *fat;
	char *cmdline;
	unsigned char langmode, langbyte1;
};
struct TASKLEVEL {
	int running; /*正在运行的任务数量*/
	int now; /*这个变量用来记录当前正在运行的是哪个任务*/
	struct TASK *tasks[MAX_TASKS_LV];
};
struct TASKCTL {
	int now_lv; /*现在活动中的LEVEL */
	char lv_change; /*在下次任务切换时是否需要改变LEVEL */
	struct TASKLEVEL level[MAX_TASKLEVELS];
	struct TASK tasks0[MAX_TASKS];
};
extern struct TASKCTL *taskctl;
extern struct TIMER *task_timer;
struct TASK *task_now(void);
struct TASK *task_init(struct MEMMAN *memman);
struct TASK *task_alloc(void);
void task_run(struct TASK *task, int level, int priority);
void task_switch(void);
void task_sleep(struct TASK *task);

/* window.c */
void make_box(struct SHEET *sht, int x1, int y1, int x2, int y2, int bbc, int bgc, char *txt, int tc, int ta, int margin);
void make_window8(unsigned int *buf, int xsize, int ysize, char *title, char act);
void putfonts8_asc_sht(struct SHEET *sht, int x, int y, int c, int b, char *s, int l);
void make_textbox8(struct SHEET *sht, int x0, int y0, int sx, int sy, int c);
void make_wtitle8(unsigned int *buf, int xsize, char *title, char act);
void change_wtitle8(struct SHEET *sht, char act);
struct ONMOUSEMENU {
  int id; //作为菜单唯一标识
  int x0, y0, x1, y1;
  int flag; //0正常,1改色, 点击时作为方法地址传参
  int bgcolor, bgcolorchg;
};
struct ONMOUSEEVEN {
  struct SHEET *sht;
  struct ONMOUSEMENU onms[MAX_SHEETS];
};
extern struct ONMOUSEEVEN *onmover;
extern struct ONMOUSEEVEN *onmclick;
void mouseover_init();
int  mouseover_getsize(struct SHEET *sht);
void mouseover_del(struct SHEET *sht);
void mouseover_delsub(struct SHEET *sht, int id);
int  mouseover_set(struct SHEET *sht, int x0, int y0, int x1, int y1, int bgc, int bgcchg, int id);
void mouseclick_init();
int  mouseclick_getsize(struct SHEET *sht);
void mouseclick_del(struct SHEET *sht);
void mouseclick_delsub(struct SHEET *sht, int id);
int  mouseclick_set(struct SHEET *sht, int x0, int y0, int x1, int y1, int func, int id);
void window_onmouseover(struct SHEET *sht, int mx, int my);
void window_onmouseclick(struct SHEET *sht, int mx, int my);

/* console.c */
struct CONSOLE {
	struct SHEET *sht;
	int cur_x, cur_y, cur_c;
	struct TIMER *timer;
};
struct FILEHANDLE {
	char *buf;
	int size;
	int pos;
};
void console_task(struct SHEET *sheet, int memtotal);
void cons_putchar(struct CONSOLE *cons, int chr, char move);
void cons_newline(struct CONSOLE *cons);
void cons_putstr0(struct CONSOLE *cons, char *s);
void cons_putstr1(struct CONSOLE *cons, char *s, int l);
void cons_runcmd(char *cmdline, struct CONSOLE *cons, int *fat, int memtotal);
void cmd_mem(struct CONSOLE *cons, int memtotal);
void cmd_cls(struct CONSOLE *cons);
void cmd_dir(struct CONSOLE *cons);
void cmd_exit(struct CONSOLE *cons, int *fat);
void cmd_start(struct CONSOLE *cons, char *cmdline, int memtotal);
void cmd_ncst(struct CONSOLE *cons, char *cmdline, int memtotal);
void cmd_langmode(struct CONSOLE *cons, char *cmdline);
int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline);
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax);
int *inthandler0d(int *esp);
int *inthandler0c(int *esp);
void hrb_api_linewin(struct SHEET *sht, int x0, int y0, int x1, int y1, int col);
void cmd_reboot();

/* file.c */
struct FILEINFO {
	unsigned char name[8], ext[3], type;
	char reserve[10];
	unsigned short time, date, clustno;
	unsigned int size;
};
void file_readfat(int *fat, unsigned char *img);
void file_loadfile(int clustno, int size, char *buf, int *fat, char *img);
struct FILEINFO *file_search(char *name, struct FILEINFO *finfo, int max);
char *file_loadfile2(int clustno, int *psize, int *fat);

/* tek.c */
int tek_getsize(unsigned char *p);
int tek_decomp(unsigned char *p, char *q, int size);

/* bootpack.c */
extern struct SHEET* sht_back;
extern struct SHEET* sht_start;
extern struct SHEET* sht_taskbar;
extern int LANGUAGE_INPUT_MODE; //当前输入法 0.英文 1.中文(五笔)
struct TASK *open_constask(struct SHEET *sht, unsigned int memtotal);
struct SHEET *open_console(struct SHTCTL *shtctl, unsigned int memtotal);
void keywin_on(struct SHEET *key_win);

/*language.c*/
#define ASCLL 0
#define JAPANSE 1
#define JPEUC 2
#define CHINESE 3
#define MAX_LANGUAGE_NUMBER 10
#define LANGUAGE_NUMBER_NOW 4
extern int languages[MAX_LANGUAGE_NUMBER];
void language_init(void);//初始化语言

// cmos.c
/**CMOS操作端口**/
#define cmos_index 0x70
#define cmos_data 0x71
/**CMOS中相关信息偏移*/
#define CMOS_CUR_SEC	0x0			//CMOS中当前秒值(BCD)
#define CMOS_ALA_SEC	0x1			//CMOS中报警秒值(BCD)
#define CMOS_CUR_MIN	0x2			//CMOS中当前分钟(BCD)
#define CMOS_ALA_MIN	0x3			//CMOS中报警分钟(BCD)
#define CMOS_CUR_HOUR	0x4			//CMOS中当前小时(BCD)
#define CMOS_ALA_HOUR	0x5			//CMOS中报警小时(BCD)
#define CMOS_WEEK_DAY	0x6			//CMOS中一周中当前天(BCD)
#define CMOS_MON_DAY	0x7			//CMOS中一月中当前日(BCD)
#define CMOS_CUR_MON	0x8			//CMOS中当前月份(BCD)
#define CMOS_CUR_YEAR	0x9			//CMOS中当前年份(BCD)
#define CMOS_DEV_TYPE	0x12		//CMOS中驱动器格式
#define CMOS_CUR_CEN	0x32		//CMOS中当前世纪(BCD)

#define BCD_HEX(n)	((n >> 4) * 10) + (n & 0xf)  //BCD转16进制

#define BCD_ASCII_first(n)	(((n<<4)>>4)+0x30)  //取BC的个位并以字符输出,来自UdoOS
#define BCD_ASCII_S(n)	((n<<4)+0x30)  //取BCD的十位并以字符输出,来自UdoOS

unsigned int get_hour_hex();
unsigned int get_min_hex();
unsigned int get_sec_hex();
unsigned int get_day_of_month();
unsigned int get_day_of_week();
unsigned int get_mon_hex();
unsigned int get_year();

/* acpi.c 关机相关 */
struct ACPI_RSDP {
	char Signature[8];
	unsigned char Checksum;
	char OEMID[6];
	unsigned char Revision;
	unsigned int RsdtAddress;
	unsigned int Length;
	unsigned int XsdtAddress[2];
	unsigned char ExtendedChecksum;
	unsigned char Reserved[3];
};

struct ACPISDTHeader {
  char Signature[4];
  unsigned int Length;
  unsigned char Revision;
  unsigned char Checksum;
  char OEMID[6];
  char OEMTableID[8];
  unsigned int OEMRevision;
  unsigned int CreatorID;
  unsigned int CreatorRevision;
};

struct ACPI_RSDT {
	struct ACPISDTHeader header;
	unsigned int Entry;
};

typedef struct
{
  unsigned char AddressSpace;
  unsigned char BitWidth;
  unsigned char BitOffset;
  unsigned char AccessSize;
  unsigned int Address[2];
} GenericAddressStructure;

struct ACPI_FADT
{
    struct   ACPISDTHeader h;
    unsigned int FirmwareCtrl;
    unsigned int Dsdt;
 
    // field used in ACPI 1.0; no longer in use, for compatibility only
    unsigned char  Reserved;
 
    unsigned char  PreferredPowerManagementProfile;
    unsigned short SCI_Interrupt;
    unsigned int SMI_CommandPort;
    unsigned char  AcpiEnable;
    unsigned char  AcpiDisable;
    unsigned char  S4BIOS_REQ;
    unsigned char  PSTATE_Control;
    unsigned int PM1aEventBlock;
    unsigned int PM1bEventBlock;
    unsigned int PM1aControlBlock;
    unsigned int PM1bControlBlock;
    unsigned int PM2ControlBlock;
    unsigned int PMTimerBlock;
    unsigned int GPE0Block;
    unsigned int GPE1Block;
    unsigned char  PM1EventLength;
    unsigned char  PM1ControlLength;
    unsigned char  PM2ControlLength;
    unsigned char  PMTimerLength;
    unsigned char  GPE0Length;
    unsigned char  GPE1Length;
    unsigned char  GPE1Base;
    unsigned char  CStateControl;
    unsigned short WorstC2Latency;
    unsigned short WorstC3Latency;
    unsigned short FlushSize;
    unsigned short FlushStride;
    unsigned char  DutyOffset;
    unsigned char  DutyWidth;
    unsigned char  DayAlarm;
    unsigned char  MonthAlarm;
    unsigned char  Century;
 
    // reserved in ACPI 1.0; used since ACPI 2.0+
    unsigned short BootArchitectureFlags;
 
    unsigned char  Reserved2;
    unsigned int Flags;
 
    // 12 byte structure; see below for details
    GenericAddressStructure ResetReg;
 
    unsigned char  ResetValue;
    unsigned char  Reserved3[3];
 
    // 64bit pointers - Available on ACPI 2.0+
    unsigned int                X_FirmwareControl[2];
    unsigned int                X_Dsdt[2];
 
    GenericAddressStructure X_PM1aEventBlock;
    GenericAddressStructure X_PM1bEventBlock;
    GenericAddressStructure X_PM1aControlBlock;
    GenericAddressStructure X_PM1bControlBlock;
    GenericAddressStructure X_PM2ControlBlock;
    GenericAddressStructure X_PMTimerBlock;
    GenericAddressStructure X_GPE0Block;
    GenericAddressStructure X_GPE1Block;
};
void init_acpi(void);
int acpi_shutdown(void);

/*cpu.c*/
/* bootpack.h 中添加 */
#define CPUID_VENDOR_INTEL    "GenuineIntel"
#define CPUID_VENDOR_AMD      "AuthenticAMD"
#define CPUID_VENDOR_VIA      "CentaurHauls"

/* CPU 信息结构体 */
struct CPU_INFO {
  char vendor_id[13];         // 厂商ID字符串
  char brand_string[49];      // 品牌字符串
  unsigned int max_func;      // 最大标准功能号
  unsigned int max_ext_func;  // 最大扩展功能号
  unsigned int features_ecx;  // 功能标志 ECX
  unsigned int features_edx;  // 功能标志 EDX
};


/* 函数声明 */
void get_cpu_info(struct CPU_INFO *info);
void print_cpu_info(int x, int y);
